import java.util.Arrays;
/**
 * 数组
 * 1.数组是引用类型
 * 2.数组的应用场景
 */
public class Test {
    /**
     * Arrays常见方法
     * binarySearch(有序数组数组名)->二分查找
     * copyOf(源数组名,新数组元素个数) ->数组拷贝
     * copyOfRange(源数组名,从哪里下标开始拷贝,从哪里下标结束拷贝) ->数组下标范围拷贝
     * equals(数组名,数组名)->数组比较函数
     * fill(需要填充的数组名,填充值)/(需要填充的数组名,从哪里下标开始填充,到哪里下标结束填充,填充值)->全局填充/局部填充(范围[))
     * sort(待排序数组名)->数组排序
     * toString(数组名)->数组转字符串
     */
    public static void main(String[] args) {
        int[] array = new int[10];

//        Arrays.fill(array,99);//全局填充
        Arrays.fill(array,1,3,99);//局部填充[)

        System.out.println(Arrays.toString(array));
    }

    /**
     * 数组练习
     * @param args
     */
    /**
     * 二分查找
     * @param args
     * 类 Arrays
     * 包 java.util.Arrays
     * 方法 1.binarySearch(排序好的数组名,需要查找的数字),二分查找
     * 2.sort(待排序数组),排序数组
     */
    public static int binarySearch(int[] array,int key) {
        int left = 0;
        int right = array.length - 1;
        int mid = 0;
        while(left <= right) {

            mid = (left + right) / 2;
            if(array[mid] > key) {//大于->mid变小
                right = mid - 1;
            }else if(array[mid] < key) {
                left = mid + 1;
            }else {
                return mid;
            }
        }

        return -1;
    }
    public static void main14(String[] args) {
        int[] array = {1,2,3,4,70,94};

        //排序
        Arrays.sort(array);

        //调用方法
        int ret = binarySearch(array,100);

        System.out.println(ret);
    }

    /**
     * 字符串拷贝方法
     * 类: Arrays
     * 包: java.util.Arrays
     * 类方法: 1.copyOf(被拷贝数组名,数组长度(可以进行更改))->字符串拷贝
     * 2.copyOfRance(被拷贝数组名,从哪里下标开始拷贝,到哪里下标结束);范围 : [)->指定范围拷贝
     *
     * //克隆拷贝
     * 数组名.clone()
     */

    //模拟实现copyOf
    public static int[] myCopyOf(int[] array) {
        int[] dest = new int[array.length];

        for(int i = 0;i < array.length;i++) {
            dest[i]  = array[i];
        }

        return dest;
    }
    public static void main13(String[] args) {
        int[] array = {1,2,3,4,5};

        int[] ret = myCopyOf(array);

        System.out.println(Arrays.toString(ret));
    }
    public static void main12(String[] args) {
        int[] array = {1,2,3,4,5};

        int[] ret = array.clone();

        System.out.println(Arrays.toString(ret));
    }
    public static void main11(String[] args) {
        int[] array = {1,2,3,4,5};

        int[] ret = Arrays.copyOfRange(array,1,3);

        System.out.println(Arrays.toString(ret));
    }
    public static void main10(String[] args) {
        int[] array = {1, 2, 3, 4, 5};

        int[] ret = Arrays.copyOf(array, array.length);

        System.out.println(Arrays.toString(ret));
    }
    /**
     * 数组转为字符串
     * @param args
     */
    public static String myToString(int[] array) {
        if(array == null) {
            return "null";
        }

        String ret = "[";

        for(int i = 0;i < array.length;i++) {
            ret += array[i];
            if(i != array.length - 1) {
                ret += ",";
            }
        }

        ret += "]";

        return ret;
    }
    public static void main9(String[] args) {
        int[] array = {1,2,3,4,5};
       System.out.println(myToString(array));
    }

    /**
     * 数组的应用场景
     * 1.保存数据
     * 2.作为函数参数
     * 3.作为函数返回值
     */

    public static int[] func2() {
        int[] array = {1,2,3,4,5};
        return array;
    }
    public static void main8(String[] args) {
        /**
         * 作为函数返回值
         * @param args
         */

        int[] ret = func2();

        System.out.println(Arrays.toString(ret));
    }
    public static void func1(int[] array) {
        array[0] = 100;
    }
    public static void main7(String[] args) {
        /**
         * 作为方法参数
         * @param args
         * 本质上,形参指向了实参指向的对象地址
         * 通过操作变量来改变实参指向的对象
         */
        int[] array = {1,2,3,4,5};

        func1(array);

        System.out.println(Arrays.toString(array));
    }
    public static void main6(String[] args) {
        /**
         * 保存数据
         * 存储相同类型元素
         */
        int[] array = new int[5];
        for(int i = 0;i < array.length;i++) {
            array[i] = i;
        }

        for(int i = 0;i < array.length;i++) {
            System.out.print(array[i] + " ");
        }
    }

    /**
     * 数组是引用类型
     * 1.初识JVM
     * 2.基本数据类型变量与引用类型变量的区别
     * 3.再谈引用变量
     * 4.认识null
     * @param args
     */

    /**
     * 认识null
     * 1.表示不指向任何对象,所以不能对该引用类型,做出任何操作
     * 2.null与0没有任何关系
     */
    public static void main5(String[] args) {
        int[] array = null;
        int len = array.length;//error,指向对象为null,不能进行任何操作
    }

    /**
     * 再谈引用变量
     * @param args
     * 1.引用变量的本质就是,存储指向对象的起始地址
     * 2.通过变量可以操作对象
     */
    public static void func() {
        int[] array1 = new int[3];
        array1[0] = 10;
        array1[1] = 20;
        array1[2] = 30;
        int[] array2 = new int[]{1,2,3,4,5};
        array2[0] = 100;
        array2[1] = 200;
        array1 = array2;
        array1[2] = 300;
        array1[3] = 400;
        array2[4] = 500;
        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i]);
        }
    }
    public static void main4(String[] args) {
        func();
    }
    /**
     * 2.基本数据类型变量与引用类型变量的区别
     */
    public static void main3(String[] args) {
        /**
         * 基本数据类型变量->基本变量
         * 变量空间直接存储的是其对应的值
         */
        int a = 10;
        System.out.println(a);

        /**
         * 引用类型变量->对象的引用
         * 一般不是直接存储对应的值,而是存储指向对象的地址
         * 一般不是存储对象本身,而是存储对象的起始地址,通过变量来操作对象.
         */
        int[] array = {1,2,3,4,5};
        System.out.println(array);
    }

    /**
     * 1.初识JVM:分为五大部分,方法区 堆 虚拟机栈 程序计数器 本地方法栈
     */
    public static void main2(String[] args) {
        /**
         * 方法区:经过编译器编译后的代码等数据
         * 包含: 常量 静态常量 类信息...
         */

        /**
         * 堆: JVM的最大内存区域,new对象需要的空间都存放在堆中
         * 堆随着程序开始而创建,随着程序的结束而销毁,如果还在使用就不会被销毁
         */

        /**
         * 虚拟机栈:与方法调用相关的信息
         * 每个方法在执行时,都会先创建一个栈帧
         * 栈帧中包含,局部变量(主要记住这个),操作数栈,动态链接,返回地址等其他信息
         * 随着方法的执行而创建,随着方法的结束而销毁
         */

        /**
         * 程序计数器:保存下一条指令的地址
         */

        /**
         * 本地方法栈: 与虚拟机栈类似,不过保存的是Native方法局部变量
         */
    }
    public static void main1(String[] args) {
        /**
         * 数组以字符串返回
         * Arrays.toString
         * 导包 java.util.Arrays
         * 基本数据包装类型.toString->转化成字符串
         */
        int[] array = {1,2,3,4,5};
        String ret = Arrays.toString(array);
        String ret2 = Integer.toString(100);
        System.out.println(ret);
        System.out.println(ret2);
    }
}
